package ca.mcgill.schedulability.singleevent.utils;

import ca.mcgill.model.digraph.Digraph;
import ca.mcgill.model.digraph.TransactionEdge;
import ca.mcgill.model.functional.Transition;
import ca.mcgill.model.functional.triggering.Event;
import ca.mcgill.model.functional.triggering.ExternalEvent;
import ca.mcgill.schedulability.singleevent.model.SingleEventChain;


public class FindOffsets {
	
	
	public void computeOffsets(SingleEventChain T, int p){
		
		double minExecTime = 100; boolean firstTime = true;
		
		Digraph currentDigraph =  T.getImplDigraphs().get(p);
		Digraph previousDigraph =  T.getImplDigraphs().get(p-1);

		for ( Transition myTransition : currentDigraph.getVertices() ){
			
			Event myEvent = myTransition.getTrigE();
			

			// TODO: Optimization --> add a list of already visited events 
			// to avoid executing the next for loop again.
			
			for ( Transition prTransition : previousDigraph.getVertices() ){
				
				Event prEvent = prTransition.getOutE();
				if (prEvent.equals(myEvent)){
					if (firstTime){
						minExecTime = prTransition.getAction().getBCET();
						firstTime = false;
					}else{
						if (minExecTime > prTransition.getAction().getBCET()){
							minExecTime = prTransition.getAction().getBCET();
						}
					}
				}	
			}

			// here you have found the offsets --> add them as edges
			//OffsetEdge newOffsetEdge = new OffsetEdge(minExecTime, prTran myTransition, false);
			//currentDigraph.addEdge(newOffsetEdge);		
		}
		
	}
	


	public double computeInitialOffsets(SingleEventChain T, Transition myTransition, int phase){
		
		
		// the current method computes the offsets for the 
		// first digraph of a chain based on the execution path (total execution time)
					
		double maxExecTime = myTransition.getAction().getWCET();
		double InitialOffset;

		// and the starting from the last digraph go backwards till the one @ the phase
		int sizeOfChain = T.getImplDigraphs().size();
		double tmpExecTime;
		Transition targetTrans = myTransition;
		
		
		for (int i=sizeOfChain-1; i>=phase;i--) {
	
			tmpExecTime = 0;
			Digraph previousDigraph =  T.getImplDigraphs().get(i);

			Event targetEvent = targetTrans.getTrigE();
			
			for ( Transition trans : previousDigraph.getVertices() ){

				Event prEvent = trans.getOutE();
				if (targetEvent.equals(prEvent)){
					if (tmpExecTime > trans.getAction().getBCET()){
						tmpExecTime = trans.getAction().getBCET();
						targetTrans = trans;
					}					
				}
			}
			
			maxExecTime += tmpExecTime;

		}

		ExternalEvent myEvent;
		myEvent = (ExternalEvent) T.getImplModel().getImplementedNetwork().getFsms().get(0).getTransitions().get(0).getTrigE();	
		// that is my global deadline for this case of one external event
		double myPeriod = (double) myEvent.getPeriod();
		InitialOffset = myPeriod - maxExecTime;
		
		return InitialOffset;
	}
	
	

}
